﻿using System.Collections.Concurrent;
using Anderson.NetLobby.Client;
using UnityEngine;
using UnityEngine.UI;
using Anderson.NetLobby.Common;
using System.Collections;
using UnityEngine.SceneManagement;
using System;

public class DemoClient : MonoBehaviour {

    public Button ConnectButton;
    public Button DisconnectButton;
    public Button CreateRoomButton;
    public Button ListRoomButton;
    public Button EnterRoomButton;
    public Button ExitRoomButton;
    public Button RoomStartButton;
    public Button CloseRoomButton;

    public InputField InputFieldFrameCount;
    public InputField InputFieldRoomId;

    public InputField InputFieldHost;
    public InputField InputFieldPort;

    private NetLobbyClientEx client;

    #region Static
    public static NetLobbyClientEx ClientInstance = null;
    #endregion


    private void Start()
    {
        ConnectButton.onClick.AddListener(OnConnect);
        DisconnectButton.onClick.AddListener(OnDisconnect);

        CreateRoomButton.onClick.AddListener(OnCreateRoom);
        ListRoomButton.onClick.AddListener(OnListRoom);
        EnterRoomButton.onClick.AddListener(OnEnterRoomButton);
        ExitRoomButton.onClick.AddListener(OnExitRoomButton);
        CloseRoomButton.onClick.AddListener(OnCloseRoomButton);

        RoomStartButton.onClick.AddListener(OnRoomStartButton);
    }

    ConcurrentQueue<HeartCallback> queueLongCallback = new ConcurrentQueue<HeartCallback>();
    ConcurrentQueue<Action> normalActionQueue = new ConcurrentQueue<Action>();
    Action normalAction;
    HeartCallback heartCallback;
    void Update()
    {
        while (queueLongCallback.TryDequeue(out heartCallback))
        {
            heartCallback.action.Invoke(heartCallback.param);
        }

        while (normalActionQueue.TryDequeue(out normalAction))
        {
            normalAction.Invoke();
        }
    }

    void OnDisconnect()
    {
        if (null != client)
        {
            client.Disconnect();
            client = null;

            ClientInstance = null;
        }
    }

    private void OnDestroy()
    {
        OnDisconnect();
    }

    void OnConnect()
    {
        if (null == client)
        {
            string host = InputFieldHost.text;
            int port = int.Parse(InputFieldPort.text);

            client = new NetLobbyClientEx(host, port, "aaa", new UnityLogger(), new HeartCallback(OnHeart), queueLongCallback);
            ClientInstance = client;

            client.RoomStarted = OnRoomStarted;
            client.RoomStoped = OnRoomStoped;
            client.BusinessMessageReceive = OnBusinessMessageReceive;
        }

        client.Connect();        
    }

    void OnCreateRoom()
    {
        client.CreateRoom();
    }

    void OnListRoom()
    {
        client.ListRoom();
    }

    void OnEnterRoomButton()
    {
        long roomId = int.Parse(InputFieldRoomId.text);
        client.EnterRoom(roomId);
    }

    void OnExitRoomButton()
    {
        client.ExitRoom();
    }

    private void OnRoomStartButton()
    {
        client.StartRoom();
    }

    private void OnCloseRoomButton()
    {
        client.CloseRoom();
    }

    #region ClientEvent
    void OnHeart(long frameCount)
    {
        InputFieldFrameCount.text = "" + frameCount;
    }

    void OnRoomStarted(long roomId)
    {
        normalActionQueue.Enqueue(() => { StartCoroutine(LoadRoomScene()); });
    }

    void OnRoomStoped(long roomId)
    {
        normalActionQueue.Enqueue(() => { StartCoroutine(UnLoadRoomScene()); });
    }

    private void OnBusinessMessageReceive(byte[] fullMessageBytes, long roomId, uint l1, uint l2, uint l3)
    {
        Debug.Log("DemoClient.OnBusinessMessageReceive");

        if (null == demoRoom)
        {
            demoRoom = DemoRoom.Instance;

            if (demoRoom == null)
            {
                Debug.Log("DemoClient.demoRoom == null");
            }      
        }

        demoRoom.OnBusinessMessageReceive(fullMessageBytes, roomId, l1, l2, l3);
    }
    #endregion

    #region RoomScene
    DemoRoom demoRoom = null;
    const string RoomSceneName = "DemoRoom";
    IEnumerator LoadRoomScene()
    {
        AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(RoomSceneName, LoadSceneMode.Additive);

        while (!asyncLoad.isDone)
        {
            break;
        }

        Debug.Log("DemoClient.LoadRoomScene Done");

        //Not working
        //Scene s = SceneManager.GetSceneByName(RoomSceneName);
        //List<GameObject> list = new List<GameObject>();
        //s.GetRootGameObjects(list);
        //foreach (GameObject go in list)
        //{
        //    if ("DemoRooBrain".Equals(go.name))
        //    {
        //        demoRoom = go.GetComponent<DemoRoom>();
        //        break;
        //    }
        //}        
        //Debug.LogFormat("DemoClient.demoRoom found : {0}", null == demoRoom ? "False" : "True");

        yield break;
    }

    private IEnumerator UnLoadRoomScene()
    {
        AsyncOperation asyncUnLoad = SceneManager.UnloadSceneAsync(RoomSceneName);

        while (!asyncUnLoad.isDone)
        {
            break;
        }

        demoRoom = null;

        Debug.Log("DemoClient.UnLoadRoomScene Done");

        yield break;
    }
    #endregion

}
